package pckg;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Line2D.Double;
import java.util.List;

import pckg.realRobot.RealRobot;

public class RobotDrawer {
	
	private static final Color idealColor = Color.RED;
	private static final Color robotColor = Color.BLUE;
	private static final Color nnvColor = Color.GREEN;
	private static final Color nnspColor = Color.DARK_GRAY;
	private static final Color surfColor = Color.MAGENTA;
	private static final Color decColor = Color.BLACK;
	
	//private static final Color cmdColor = Color.ORANGE;
	private static final Color cmdColor = new Color((Color.ORANGE).getColorSpace(),(Color.ORANGE).getColorComponents(new float[3]),0.3f);

	public static void draw(Graphics g, RealRobot robot, RealRobot nnvRobot, RealRobot nnspRobot, RealRobot surfRobot, RealRobot decomposer){
		g.setColor(robotColor);
		Graphics2D g2d = (Graphics2D)g;
		Rectangle2D body = new Rectangle2D.Double(((robot.getX()-RealLifeProperties.d)*Simulator.scale)+Simulator.getMidX(),
													(((-1)*robot.getY()-RealLifeProperties.l)*Simulator.scale)+Simulator.getMidY(),
													(RealLifeProperties.d*2*Simulator.scale),
													(RealLifeProperties.l*2*Simulator.scale));
		AffineTransform trans = new AffineTransform();
		trans.rotate((-1)*robot.getOrient(), robot.getX()*Simulator.scale+Simulator.getMidX(), (-1)*robot.getY()*Simulator.scale+Simulator.getMidY());
		Shape rotatedBody = trans.createTransformedShape(body);
		
		g2d.draw(rotatedBody);
		
		Double line1 = new Line2D.Double((robot.getX()-RealLifeProperties.d)*Simulator.scale+Simulator.getMidX(),
											(-1)*(robot.getY()-RealLifeProperties.l)*Simulator.scale+Simulator.getMidY(),
											(robot.getX()+RealLifeProperties.d)*Simulator.scale+Simulator.getMidX(),
											(-1)*(robot.getY())*Simulator.scale+Simulator.getMidY());
		Double line2 = new Line2D.Double((robot.getX()-RealLifeProperties.d)*Simulator.scale+Simulator.getMidX(),
											(-1)*(robot.getY()+RealLifeProperties.l)*Simulator.scale+Simulator.getMidY(),
											(robot.getX()+RealLifeProperties.d)*Simulator.scale+Simulator.getMidX(),
											(-1)*(robot.getY())*Simulator.scale+Simulator.getMidY());
		g2d.draw(trans.createTransformedShape(line1));
		g2d.draw(trans.createTransformedShape(line2));
		
		if (true){
			g.setColor(robotColor);
			drawLine(g,robot.getPath(),robot.getCmds());
			
			g.setColor(cmdColor);
			drawCmds(g,robot.getCmds());
		}
		
		if (true){
			g.setColor(idealColor);
			drawLine(g,robot.getIdealPath(),robot.getIdealCmds());
			if (robot.getIdealCmds().size() != 0){
				drawCircle(g,robot.getIdealCmds().get(robot.getIdealCmds().size()-1));
			}
			
			g.setColor(cmdColor);
			drawCmds(g,robot.getIdealCmds());
		}
		
		if (Main.vNN){
			g.setColor(nnvColor);
			drawLine(g,nnvRobot.getPath(),nnvRobot.getCmds());
			g.setColor(cmdColor);
			drawCmds(g,nnvRobot.getCmds());
		}
		
		if (Main.spNN){
			g.setColor(nnspColor);
			drawLine(g,nnspRobot.getPath(),nnspRobot.getCmds());
			g.setColor(cmdColor);
			drawCmds(g,nnspRobot.getCmds());
		}
		
		if (Main.surfB){
			g.setColor(surfColor);
			drawLine(g,surfRobot.getPath(),surfRobot.getCmds());
			if (surfRobot.getCmds().size() != 0){
				drawCircle(g,surfRobot.getCmds().get(surfRobot.getCmds().size()-1));
			}
			
			g.setColor(cmdColor);
			//drawCmds(g,surfRobot.getCmds());
		}
		
		if (Main.dec){
			g.setColor(decColor);
			drawLine(g,decomposer.getPath(),decomposer.getCmds());
			if (decomposer.getCmds().size() != 0){
				drawCircle(g,decomposer.getCmds().get(decomposer.getCmds().size()-1));
			}
			
			g.setColor(cmdColor);
			drawCmds(g,decomposer.getCmds());
		}
		
	}
	
	public static void drawLine(Graphics g, List<Vec> path, List<Vec> cmds){
		
		if (path.size() == 0){
			return;
		}
		
		for (int i = 1; i < path.size() ; i++){

				g.drawLine(	(int)(path.get(i-1).x*Simulator.scale)+Simulator.getMidX(), (int)((-1)*path.get(i-1).y*Simulator.scale)+Simulator.getMidY(), 
						(int)(path.get(i).x*Simulator.scale)+Simulator.getMidX(), (int)((-1)*path.get(i).y*Simulator.scale)+Simulator.getMidY());
		
		}
	}
	
	public static void drawCircle(Graphics g, Vec o){
		double r = 0.15;
		double delta = Math.PI/100;
		for ( double alpha = 0 ; alpha <= 2* Math.PI ; alpha += delta ){
			g.drawLine(	(int)Math.round((o.x+r*Math.cos(alpha))*Simulator.scale+Simulator.getMidX()),
					(int)Math.round(-(o.y+r*Math.sin(alpha))*Simulator.scale+Simulator.getMidY()),
					(int)Math.round((o.x+r*Math.cos(alpha+delta))*Simulator.scale+Simulator.getMidX()), 
					(int)Math.round(-(o.y+r*Math.sin(alpha+delta))*Simulator.scale+Simulator.getMidY()));
		}
	}
	
	public static void drawCmds(Graphics g, List<Vec> cmds){
		for (Vec p:cmds){
			drawPlus((Graphics2D)g,p);
		}
	}
	
	public static void drawPlus(Graphics2D g, Vec pos){
		int halfWidth = 1;
		int halfHeight = 4;
		
		Rectangle2D vert = new Rectangle2D.Double((pos.x*Simulator.scale-halfWidth)+Simulator.getMidX(), 
													((-1)*pos.y*Simulator.scale-halfHeight)+Simulator.getMidY(), 
													2*halfWidth+1, 
													2*halfHeight+1);
		g.fill(vert);
		
		Rectangle2D hor = new Rectangle2D.Double((pos.x*Simulator.scale-halfHeight)+Simulator.getMidX(), 
													((-1)*pos.y*Simulator.scale-halfWidth)+Simulator.getMidY(), 
													2*halfHeight+1, 
													2*halfWidth+1);
		g.fill(hor);
		
	}

}
